package common

import (
	"Hypnos-Soundcore/components/config"
	"Hypnos-Soundcore/constants"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/pquerna/ffjson/ffjson"
	"reflect"
)

// var .
var (
	SecurityFields = []string{"Password", "OriginalPassword", "NewPassword"}
	//AiBigFields = []string{ "Files", "Features", "Feature", }
	AiBigFields    = []string{"Files"}
	EventBigFields = []string{"Events", "ThumbData"}
)

// SaveUserLogBase 保存用户操作记录
//func SaveUserLogBase(ur *models.UserLog) (err error) {
//	if ur != nil {
//		o, _ := helper.NewOrm()
//		_, err = o.Insert(ur)
//	}
//	return err
//}

// SaveUserLog 保存用户操作记录到数据库，暂不使用
func SaveUserLog(req interface{}, superAdmin string, actionID string, subID string, stationSn string, deviceSn string) (err error) {
	if !config.IsLogUserOp() {
		return
	}
	//var paramData string
	//if req != nil {
	//	if data, ferr := ffjson.Marshal(req); ferr == nil {
	//		paramData = string(data)
	//	}
	//}
	//ur := models.UserLog{ActionUserID: superAdmin,
	//	UserLogBase: models.UserLogBase{ActionID: actionID, StationSn: stationSn,
	//		DeviceSn: deviceSn, ActionSubID: subID, ActionTime: helper.GetNowUtcTime(),
	//		ActionParams: paramData},
	//	CreateTimeColumn: models.CreateTimeColumn{CreateTime: helper.GetNowTime()}}
	//err = SaveUserLogBase(&ur)
	return
}

// TransformResponse 转换结果代码和结果消息
func TransformResponse(code int, err error) (int, string) {
	if err != nil {
		return code, err.Error()
	}
	return code, ""
}

// SaveUserLogToFileV1 将用户操作写入文件而不是数据库中
func SaveUserLogToFileV1(c *gin.Context, code int, message string, req interface{}) {
	//userID := c.GetString(auth.AuthUser)
	//fullSaveUserLogToFile(c, userID, "", "", code, message, req, nil)
}

// SaveUserLogToFileV2 将用户操作写入文件而不是数据库中
func SaveUserLogToFileV2(c *gin.Context, userID string, code int, message string, req interface{}) {
	fullSaveUserLogToFile(c, userID, "", "", code, message, req, nil)
}

// SaveUserLogToFileV3 将用户操作写入文件而不是数据库中
func SaveUserLogToFileV3(c *gin.Context, userID, stationSn string, code int, message string, req interface{}) {
	fullSaveUserLogToFile(c, userID, stationSn, "", code, message, req, nil)
}

// SaveUserLogToFileV4 将用户操作写入文件而不是数据库中
func SaveUserLogToFileV4(c *gin.Context, userID, stationSn, deviceSn string, code int, message string, req interface{}) {
	fullSaveUserLogToFile(c, userID, stationSn, deviceSn, code, message, req, nil)
}

func SaveUserLogToFileV5(c *gin.Context, code int, message string, req, resp interface{}) {
	//userID := c.GetString(auth.AuthUser)
	//fullSaveUserLogToFile(c, userID, "", "", code, message, req, resp)
}

func SaveUserLogToFileV6(c *gin.Context, code int, message, userId, stationSn, deviceSn string, req, resp interface{}) {
	fullSaveUserLogToFile(c, userId, stationSn, deviceSn, code, message, req, resp)
}

func SaveUserLogToFileV7(c *gin.Context, userId string, code int, message string, req, resp interface{}) {
	fullSaveUserLogToFile(c, userId, "", "", code, message, req, resp)
}

func SaveUserLogToFileV8(c *gin.Context, userID, stationSn string, code int, message string, req, resp interface{}) {
	fullSaveUserLogToFile(c, userID, stationSn, "", code, message, req, resp)
}

// 将用户操作写入文件而不是数据库中
func fullSaveUserLogToFile(c *gin.Context, userID, stationSn, deviceSn string, code int, message string, req, resp interface{}) {
	if config.IsLogUserOp() {
		var bs constants.IBaseRequest
		var params, response string
		if req != nil {
			if jd, _ := ffjson.Marshal(req); len(jd) > 0 {
				params = string(jd)
			}
			if ori, ok := req.(constants.IBaseRequest); ok {
				bs = ori
			}
		}
		if bs == nil {
			bs = &constants.BaseRequest{}
		}

		var path string
		if c != nil {
			path = c.Request.URL.Path
		}
		if len(message) > 0 {
			message = fmt.Sprintf("%s, %s", constants.GetTextByCodeDefault(code), message)
		} else {
			message = constants.GetTextByCodeDefault(code)
		}
		if resp != nil {
			if rs, _ := ffjson.Marshal(resp); len(rs) > 0 {
				response = string(rs)
			}
		}
		ex := constants.ExtraRequest{ExPath: path, ExUserID: userID, ExStationSn: stationSn,
			ExDeviceSn: deviceSn, ExCode: code, ExMessage: message, ExParams: params, ExParamsObject: req, ExResponseString: response}
		c.Set(constants.KeyBaseRequest, bs)
		c.Set(constants.KeyExtraRequest, &ex)
	}
}

// EncodeSecurityFields 将指定字段加密
func EncodeSecurityFields(inObj interface{}) {
	valueOfObj := reflect.ValueOf(inObj)
	if valueOfObj.Kind() != reflect.Ptr {
		return
	}
	valueOfObj = valueOfObj.Elem()
	for _, fn := range SecurityFields {
		field := valueOfObj.FieldByName(fn)
		if field.Kind() == reflect.String && field.CanSet() {
			//field.SetString(encrypt.Base64StdEncode(field.String()))
			field.SetString(constants.OperatorAsterisk)
		}
	}
}

// 清除字符串数据
func clearStringField(field reflect.Value) {
	if field.CanSet() && field.Len() > 0 {
		field.SetString(constants.OperatorAsterisk)
	}
}

// ClearBigFields 清除字串长度很大的字段，例如文件数据字段，AI特征字段，避免日志文件过大
func ClearBigFields(inObj interface{}, bigFields []string) {
	var ok bool
	valueOfObj := reflect.ValueOf(inObj)
	switch valueOfObj.Kind() {
	case reflect.Ptr:
		valueOfObj = valueOfObj.Elem()
	case reflect.Struct:
		if valueOfObj, ok = inObj.(reflect.Value); ok && valueOfObj.Kind() == reflect.Ptr {
			valueOfObj = valueOfObj.Elem()
		} else {
			return
		}
	default:
		return
	}
	for _, fn := range bigFields {
		field := valueOfObj.FieldByName(fn)
		switch field.Kind() {
		case reflect.String:
			clearStringField(field)
		case reflect.Ptr:
			if field = field.Elem(); field.Kind() == reflect.String {
				clearStringField(field)
			}
		case reflect.Slice:
			for i := 0; i < field.Len(); i++ {
				item := field.Index(i)
				switch item.Kind() {
				case reflect.String:
					clearStringField(item)
				case reflect.Struct:
					if item.CanAddr() {
						ClearBigFields(item.Addr(), bigFields)
					}
				default:
				}
			}
		default:
		}
	}
}
